package com.hq.ims.data.config.bean;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.hq.ims.data.entity.Company;
import com.hq.ims.data.interceptor.sql.XmlSqlDataRangeInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * jiang bai ping
 *
 * @Email 526666031@qq.com
 */
@Configuration
public class BeanDefConfig {

    public static final String REDIS_COMPANY_KEY = "redisCompany";

    // ---------------------------------- mybatisPlus ----------------------------------

    /**
     * Mybatis插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setOptimizeJoin(false);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

    @Bean
    @DependsOn("mybatisPlusInterceptor")
    public XmlSqlDataRangeInterceptor XmlSqlDataRangeInterceptor(){
        return new XmlSqlDataRangeInterceptor();
    }

    // ---------------------------------- redisBean ----------------------------------

    /**
     * 公司存储
     *
     * @return
     */
    @Bean(name = BeanDefConfig.REDIS_COMPANY_KEY)
    public RedisTemplate<String, Company> redisCompany(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Company> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        return redisTemplate;
    }


    // ---------------------------------- 线程 ----------------------------------
    @Bean
    public ThreadPoolExecutor workThreadExecutor() {
        /*
         * 线程池中的饱和策略
         * 1. ThreadPoolExecutor.AbortPolicy: 抛出RejectedExecutoionExpection来拒绝新任务的处理
         * 2. ThreadPoolExecutor.CallerRunsPolicy: 调用执行自己的线程运行任务，也就是直接调用execute方法线程中运行被拒绝的任务，如果执行程序已关闭，则会丢弃该任务。因此这种策略会降低对于新任务提交的速度，
         * 影响程序的整体性能。
         * 3. ThreadPoolExecutor.DiscardPolicy: 不处理新任务，直接丢弃
         * 4. ThreadPoolExecutor.DiscardOldestPolicy: 此策略将丢弃最早的未处理的任务请求
         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                50, 2000, 60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(100),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
        return executor;
    }

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(50);
        return taskScheduler;
    }

}
